imcontext: Make Compose preedit less intrusive
authorMatthias Clasen <mclasen@redhat.com>
Thu, 18 Feb 2021 00:59:28 +0000 (19:59 -0500)
committerMatthias Clasen <mclasen@redhat.com>
Thu, 18 Feb 2021 16:44:09 +0000 (11:44 -0500)
Tweak the preedit display for Compose sequences to
be not so distracting. We only show the Compose key
when it occurs in the middle of the sequence or is
the only key so far, and use · instead of ⎄ for it.

Also, make sure to display dead keys more adequately.

gtk/gtkimcontextsimple.c

index b8fec2f384113cd2a44f9a0c9127cde8a6e2e955..86e133fc8674dbcc5c5419a55e8b53646ce300ae 100644 (file)
@@ -930,9 +930,99 @@ gtk_im_context_simple_get_preedit_string (GtkIMContext   *context,
       for (i = 0; priv->compose_buffer[i]; i++)
         {
           if (priv->compose_buffer[i] == GDK_KEY_Multi_key)
-            g_string_append_unichar (s, 0x2384); /* U+2384 COMPOSITION SYMBOL */
+            {
+              /* We only show the Compose key visibly when it is the
+               * only glyph in the preedit, or when it occurs in the
+               * middle of the sequence. Sadly, the official character,
+               * U+2384, COMPOSITION SYMBOL, is bit too distracting, so
+               * we use U+00B7, MIDDLE DOT.
+               */
+              if (priv->compose_buffer[1] == 0 || i > 0)
+                g_string_append (s, "·");
+            }
           else
-            g_string_append_unichar (s, gdk_keyval_to_unicode (priv->compose_buffer[i]));
+            {
+              gunichar ch;
+              gboolean need_space;
+
+              if (GDK_KEY_dead_grave <= priv->compose_buffer[i] && priv->compose_buffer[i] <= GDK_KEY_dead_greek)
+                {
+                  /* Sadly, not all the dead keysyms have spacing mark equivalents
+                   * in Unicode. For those that don't, we use space + the non-spacing
+                   * mark as an approximation
+                   */
+                  switch (priv->compose_buffer[i])
+                    {
+#define CASE(keysym, unicode, sp) \
+                    case GDK_KEY_dead_##keysym: ch = unicode; need_space = sp; break
+
+                    CASE (grave, 0x60, 0);
+                    CASE (acute, 0xb4, 0);
+                    CASE (circumflex, 0x5e, 0);
+                    CASE (tilde, 0x7e, 0);
+                    CASE (macron, 0xaf, 0);
+                    CASE (breve, 0x2d8, 0);
+                    CASE (abovedot, 0x307, 1);
+                    CASE (diaeresis, 0xa8, 0);
+                    CASE (abovering, 0x2da, 0);
+                    CASE (hook, 0x2c0, 0);
+                    CASE (doubleacute, 0x2dd, 0);
+                    CASE (caron, 0x2c7, 0);
+                    CASE (cedilla, 0xb8, 0);
+                    CASE (ogonek, 0x2db, 0);
+                    CASE (iota, 0x37a, 0);
+                    CASE (voiced_sound, 0x3099, 1);
+                    CASE (semivoiced_sound, 0x309a, 1);
+                    CASE (belowdot, 0x323, 1);
+                    CASE (horn, 0x31b, 1);
+                    CASE (stroke, 0x335, 1);
+                    CASE (abovecomma, 0x2bc, 0);
+                    CASE (abovereversedcomma, 0x2bd, 1);
+                    CASE (doublegrave, 0x30f, 1);
+                    CASE (belowring, 0x2f3, 0);
+                    CASE (belowmacron, 0x2cd, 0);
+                    CASE (belowcircumflex, 0x32d, 1);
+                    CASE (belowtilde, 0x330, 1);
+                    CASE (belowbreve, 0x32e, 1);
+                    CASE (belowdiaeresis, 0x324, 1);
+                    CASE (invertedbreve, 0x32f, 1);
+                    CASE (belowcomma, 0x326, 1);
+                    CASE (lowline, 0x5f, 0);
+                    CASE (aboveverticalline, 0x2c8, 0);
+                    CASE (belowverticalline, 0x2cc, 0);
+                    CASE (longsolidusoverlay, 0x338, 1);
+                    CASE (a, 0x363, 1);
+                    CASE (A, 0x363, 1);
+                    CASE (e, 0x364, 1);
+                    CASE (E, 0x364, 1);
+                    CASE (i, 0x365, 1);
+                    CASE (I, 0x365, 1);
+                    CASE (o, 0x366, 1);
+                    CASE (O, 0x366, 1);
+                    CASE (u, 0x367, 1);
+                    CASE (U, 0x367, 1);
+                    CASE (small_schwa, 0x1dea, 1);
+                    CASE (capital_schwa, 0x1dea, 1);
+#undef CASE
+                    default:
+                      need_space = FALSE;
+                      ch = gdk_keyval_to_unicode (priv->compose_buffer[i]);
+                      break;
+                    }
+                  if (ch)
+                    {
+                      if (need_space)
+                        g_string_append_c (s, ' ');
+                      g_string_append_unichar (s, ch);
+                    }
+                }
+              else
+                {
+                  ch = gdk_keyval_to_unicode (priv->compose_buffer[i]);
+                  if (ch)
+                    g_string_append_unichar (s, ch);
+                }
+            }
         }
     }